package com.xzc.java8.C_Collect;

import com.alibaba.fastjson.JSON;

import java.util.*;

import static java.util.stream.Collectors.*;

public class GroupByTest {

    public static void main(String[] args) {
        List<Apple> list0 = new ArrayList<>();
        Apple a0 = new Apple("a0", "red", 150, 2011);
        Apple a1 = new Apple("a1", "red", 10, 2012);
        Apple a2 = new Apple("a2", "red", 110, 2011);
        Apple a3 = new Apple("a3", "yellow", 140, 2013);
        list0.add(a0);
        list0.add(a1);
        list0.add(a2);
        list0.add(a3);

        Map<String, List<Apple>> out0 = list0.stream().collect(groupingBy(Apple::getColor));
        System.out.println(JSON.toJSONString(out0, true));

        Map<String, Integer> out1 = list0.stream().collect(groupingBy(Apple::getColor, summingInt(Apple::getWeight)));
        System.out.println(JSON.toJSONString(out1, true));

        Map<String, Set<WeightLvl>> out2 = list0.stream().collect(groupingBy(Apple::getColor,
                mapping(a -> {
                    if (a.getWeight() < 50) return WeightLvl.LIGHT;
                    else if (a.getWeight() > 50 && a.getWeight() < 120) return WeightLvl.MID;
                    else return WeightLvl.HEAVY;
                }, toSet())));
        System.out.println(JSON.toJSONString(out2, true));

        Map<String, Set<WeightLvl>> out3 = list0.stream().collect(groupingBy(Apple::getColor,
                mapping(a -> {
                    if (a.getWeight() < 50) return WeightLvl.LIGHT;
                    else if (a.getWeight() > 50 && a.getWeight() < 120) return WeightLvl.MID;
                    else return WeightLvl.HEAVY;
                }, toCollection(HashSet::new))));
        System.out.println(JSON.toJSONString(out3, true));

        //按类型分组，如果KEY不存在，Optional也不会存在，因为groupingBy是懒加载的，只有遇到了有值才会生成对应的KEY
        Map<String, Optional<Apple>> out4 = list0.stream().collect(groupingBy(Apple::getColor, maxBy(Comparator.comparingInt(Apple::getWeight))));
        System.out.println(JSON.toJSONString(out4, true));

        //collectingAndThen 第一个参数是收集器，第二个参数是转换器,返回是一个新的转换器,这个转换器的功能就是先收集再转换
        //这个转换是安全的，因为maxBy,groupingBy，都是归约器，不会返回Optional.empty()
        //很适合用来做嵌套查询
        Map<String, Apple> out5 = list0.stream().collect(groupingBy(Apple::getColor,
                collectingAndThen(maxBy(Comparator.comparingInt(Apple::getWeight)), Optional::get)));
        System.out.println(JSON.toJSONString(out5, true));
    }
}
